﻿function Install-ServerRolesAndFeatures
{
    <# 
     .Synopsis
        This script installs the Windows Server Roles and Features required to run SharePoint 2010, SharePoint 2013, or Office Web Applications Server.

     .Description
        This script launches the PowerShell cmdlet Add-WindowsFeature with a predefined list of the roles and features required to run either SharePoint 2010, SharePoint 2013, or Office Web Applications Server. It can be launched in either "online" or "offline" mode (via the -LocalFileLocation command-line parameter). When used in "online" mode (the default), the Add-WindowsFeature cmdlet connects to Windows Update via the Internet in order to download the necessary components. If the -LocalFileLocation mode is specified, the path to the original Windows Server installation media is required.

     .Parameter LocalFileLocation
        Use this switch to indicate that the installer should use local copies of the install software instead of connecting to the Internet and downloading.
        If this switch is used, you must provide the full path to the original Windows Server installation media (e.g. E: or C:\Software\WS2012 etc.)
        NOTE: Do not include a trailing slash in the path

     .Parameter FeatureSet
       Use this parameter to indicate which feature set to install. Valid choices are 'SP2010', 'SP2013', and 'WacServer'

     .Parameter Restart
       Use this switch to automatically restart the server at the end of this script.

     .Example
       Install-ServerRolesAndFeatures -FeatureSet SP2013

     .Example
       Install-ServerRolesAndFeatures -FeatureSet WacServer -LocalFileLocation 'E:\' -Restart

    #>
    [CmdletBinding(DefaultParametersetName="OnlineInstall")]
    param([parameter(ParameterSetName = "LocalInstall", 
                     Mandatory = $true,
                     HelpMessage = "Use this parameter to indicate that the installer should use local copies of the install software instead of connecting to the Internet and downloading. If this switch is used, you must provide the full path to the original Windows 2012 installation media (e.g. E: or C:\Software\WS2012 etc.). NOTE: Do not include a trailing slash in the path")]
                     [string]$LocalFileLocation,
          [parameter(ParameterSetName = "LocalInstall", 
                     Mandatory = $true,
                     HelpMessage = "Use this parameter to indicate which feature set to install. Valid choices are 'SP2010', 'SP2013', and 'WacServer'")]
          [parameter(ParameterSetName = "OnlineInstall", 
                     Mandatory = $true,
                     HelpMessage = "Use this parameter to indicate which feature set to install. Valid choices are 'SP2010', 'SP2013', and 'WacServer'")]
                     [ValidateSet ("SP2010","SP2013","WacServer")]
                     [string]$FeatureSet,
          [parameter(ParameterSetName = "LocalInstall", 
                     Mandatory = $false,
                     HelpMessage = "Use this switch to automatically reboot at the end of this script.")]
          [parameter(ParameterSetName = "OnlineInstall", 
                     Mandatory = $false,
                     HelpMessage = "Use this switch to automatically reboot at the end of this script.")]
                     [switch]$Restart = $false)

    switch ($PSCmdlet.ParameterSetName)
    {
        "LocalInstall"
        {
            $localSourceArg = " -source " + $LocalFileLocation + "\sources\sxs"
            $installType = "Offline installation using local files"
        }
        default
        {
            $localSourceArg = ""
            $installType = "Online installation using Windows Update"
        }    
    }

	$rebootStatus = Get-PendingReboot
	if ($rebootStatus.RebootPending -eq $true)
	{
		Write-Host "NOTE: A system restart is required. Please restart the system prior to continuing with the SharePoint installation." -ForegroundColor Yellow
		Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
		throw 
	}

    # Initialize Progress Variables
    [int]$progressNumPhases = 1
    [int]$progressNumPhasesComplete = 0
    [int]$progressCurrentTask = 0
    [int]$progressTotalTasks = 1
    [int]$progressTotal = 0
    [int]$progressBarId = 100
    $startTime = [System.DateTime]::Now

    # First determine which OS we are installing on
    $osVersionMajor = [System.Environment]::OSVersion.Version.Major
    $osVersionMinor = [System.Environment]::OSVersion.Version.Minor

    # If we are installing on Windows Server 2012 R2
    if (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 3))
    {    
        $os = "WS2012"
    }
    # If we are installing on Windows Server 2012
    elseif (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 2))
    {    
        $os = "WS2012"
    }
    # If we are installing on Windows Server 2008 R2
    elseif (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 1))
    {
        $os = "W2k8R2"
    }
    else
    {
        Write-Error "This script can only be run on Windows Server 2012 or Windows Server 2008 R2"
        throw
    }
   
    # Determine the feature set to install
    if (($FeatureSet -eq "SP2010") -and ($os -eq "W2k8R2"))
    {
        Write-Warning "SP2010 Roles and Features for Windows Server 2008 R2 has not yet been implemented"
        throw
        $productName = "SharePoint 2010 Server"
        $rolesAndFeatures = @()
    }
    if (($FeatureSet -eq "SP2010") -and ($os -eq "WS2012"))
    {
        Write-Warning "SP2010 Roles and Features for Windows Server 2012 has not yet been implemented"
        throw
        $productName = "SharePoint 2010 Server"
        $rolesAndFeatures = @()
    }
    if (($FeatureSet -eq "SP2013") -and ($os -eq "WS2012"))
    {
        $productName = "SharePoint 2013 Server"
        $rolesAndFeatures = @(
			    "Net-Framework-Features",
			    "Web-Server",
			    "Web-WebServer",
			    "Web-Common-Http",
			    "Web-Static-Content",
			    "Web-Default-Doc",
			    "Web-Dir-Browsing",
			    "Web-Http-Errors",
			    "Web-App-Dev",
			    "Web-Asp-Net",
			    "Web-Net-Ext",
			    "Web-ISAPI-Ext",
			    "Web-ISAPI-Filter",
			    "Web-Health",
			    "Web-Http-Logging",
			    "Web-Log-Libraries",
			    "Web-Request-Monitor",
			    "Web-Http-Tracing",
			    "Web-Security",
			    "Web-Basic-Auth",
			    "Web-Windows-Auth",
			    "Web-Filtering",
			    "Web-Digest-Auth",
			    "Web-Performance",
			    "Web-Stat-Compression",
			    "Web-Dyn-Compression",
			    "Web-Mgmt-Tools",
			    "Web-Mgmt-Console",
			    "Web-Mgmt-Compat",
			    "Web-Metabase",
			    "Application-Server",
			    "AS-Web-Support",
			    "AS-TCP-Port-Sharing",
			    "AS-WAS-Support",
			    "AS-HTTP-Activation",
			    "AS-TCP-Activation",
			    "AS-Named-Pipes",
			    "AS-Net-Framework",
			    "WAS",
			    "WAS-Process-Model",
			    "WAS-NET-Environment",
			    "WAS-Config-APIs",
			    "Web-Lgcy-Scripting",
			    "Windows-Identity-Foundation",
			    "Server-Media-Foundation",
			    "Xps-Viewer")
    }
    if (($FeatureSet -eq "SP2013") -and ($os -eq "W2k8R2"))
    {
        Write-Warning "SP2013 Roles and Features for Windows Server 2008 R2 has not yet been implemented"
        throw
        $productName = "SharePoint 2013 Server"
        $rolesAndFeatures = @(
			    "Net-Framework-Features",
			    "Web-Server",
			    "Web-WebServer",
			    "Web-Common-Http",
			    "Web-Static-Content",
			    "Web-Default-Doc",
			    "Web-Dir-Browsing",
			    "Web-Http-Errors",
			    "Web-App-Dev",
			    "Web-Asp-Net",
			    "Web-Net-Ext",
			    "Web-ISAPI-Ext",
			    "Web-ISAPI-Filter",
			    "Web-Health",
			    "Web-Http-Logging",
			    "Web-Log-Libraries",
			    "Web-Request-Monitor",
			    "Web-Http-Tracing",
			    "Web-Security",
			    "Web-Basic-Auth",
			    "Web-Windows-Auth",
			    "Web-Filtering",
			    "Web-Digest-Auth",
			    "Web-Performance",
			    "Web-Stat-Compression",
			    "Web-Dyn-Compression",
			    "Web-Mgmt-Tools",
			    "Web-Mgmt-Console",
			    "Web-Mgmt-Compat",
			    "Web-Metabase",
			    "Application-Server",
			    "AS-Web-Support",
			    "AS-TCP-Port-Sharing",
			    "AS-WAS-Support",
			    "AS-HTTP-Activation",
			    "AS-TCP-Activation",
			    "AS-Named-Pipes",
			    "AS-Net-Framework",
			    "WAS",
			    "WAS-Process-Model",
			    "WAS-NET-Environment",
			    "WAS-Config-APIs",
			    "Web-Lgcy-Scripting",
			    "Windows-Identity-Foundation",
			    "Server-Media-Foundation",
			    "Xps-Viewer")
    }
    if (($FeatureSet -eq "WacServer") -and ($os -eq "WS2012"))
    {
        $productName = "Office Web Applications Server"
        $rolesAndFeatures = @(
                "Web-Server",
                "Web-Mgmt-Tools",
                "Web-Mgmt-Console",
                "Web-WebServer",
                "Web-Common-Http",
                "Web-Default-Doc",
                "Web-Static-Content",
                "Web-Performance",
                "Web-Stat-Compression",
                "Web-Dyn-Compression",
                "Web-Security",
                "Web-Filtering",
                "Web-Windows-Auth",
                "Web-App-Dev",
                "Web-Net-Ext45",
                "Web-Asp-Net45",
                "Web-ISAPI-Ext",
                "Web-ISAPI-Filter",
                "Web-Includes",
                "InkandHandwritingServices")
    }
    if (($FeatureSet -eq "WacServer") -and ($os -eq "W2k8R2"))
    {
        $productName = "Office Web Applications Server"
        $rolesAndFeatures = @(
            "Web-Server",
            "Web-WebServer",
            "Web-Common-Http",
            "Web-Static-Content",
            "Web-App-Dev",
            "Web-Asp-Net",
            "Web-Net-Ext",
            "Web-ISAPI-Ext",
            "Web-ISAPI-Filter",
            "Web-Includes",
            "Web-Security",
            "Web-Windows-Auth",
            "Web-Filtering",
            "Web-Stat-Compression",
            "Web-Dyn-Compression",
            "Web-Mgmt-Console",
            "Ink-Handwriting",
            "IH-Ink-Support")
    }

    Write-Host
    Write-Host "Beginning the $productName Roles and Features installation for $os."

    #region Task 1
    try
    {
        Write-Progress -Id $progressBarId -Activity "Installing $productName Roles and Features" -PercentComplete $progressTotal -CurrentOperation ("Invoking the Install-WindowsFeature cmdlet") -Status $installType
        $command = 'Add-WindowsFeature ' + [string]::join(",",$rolesAndFeatures) + $localSourceArg + " -IncludeManagementTools"

        # Execute
        $operation = Invoke-Expression $command
    
        if ($operation.RestartNeeded -eq "Yes") 
        {
            if ($Restart -eq $true)
            {
                Restart-Computer
            }
            else
            {
                Write-Host "NOTE: A system restart is required. Please restart the system prior to continuing with the SharePoint installation." -ForegroundColor Yellow
                Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
            }
        }
    }
    catch
    {
        Write-Warning "Error Adding Server Roles and Features. Error details are below:" 
        Write-Error $_ 
        break 
    }

	# Increment the progress variables for the current task
	$progressCurrentTask++
	$progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete

    #endregion

    # Increment the Phase Completion Counter
    $progressNumPhasesComplete++

    Write-Progress -Id $progressBarId -Activity "Installing $productName Roles and Features" -Status "Finishing" -PercentComplete 100 -CurrentOperation "" -Completed

    Write-Host "$productName Roles and Features installation for $os complete."
    Write-Host

}